package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseSearchDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.StringUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.query.QuestionAdminPageQuery;
import com.tianji.learning.query.QuestionPageQuery;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author Aimer
 * @since 2025-11-10
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {
    
    private final InteractionReplyMapper replyMapper;
    private final UserClient userClient;
    private final SearchClient searchClient;
    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final CategoryCache categoryCache;


    @Override
    public void addQuestion(QuestionFormDTO questionDTO) {
        // 获取当前登录用户信息
        Long userId = UserContext.getUser();
        InteractionQuestion interactionQuestion = BeanUtils.copyBean(questionDTO, InteractionQuestion.class);
        interactionQuestion.setUserId(userId);
        save(interactionQuestion);
    }

    @Override
    public PageDTO<QuestionVO> pageQuestions(QuestionPageQuery questionPageQuery) {
        // 课程id和小结id必须有一个存在
        if (questionPageQuery.getCourseId() == null && questionPageQuery.getSectionId() == null){
            throw new BadRequestException("传入的数据有误");
        }
        // 获取当前用户id
        Long userId = UserContext.getUser();
        Page<InteractionQuestion> page = lambdaQuery()
                .select(InteractionQuestion.class, info -> !info.getProperty().equals("description")) //不查询description字段
                .eq(questionPageQuery.getCourseId() != null, InteractionQuestion::getCourseId, questionPageQuery.getCourseId())
                .eq(questionPageQuery.getSectionId() != null, InteractionQuestion::getSectionId, questionPageQuery.getSectionId())
                .eq(questionPageQuery.getOnlyMine(), InteractionQuestion::getUserId, userId) // 是否只查询我的问题
                .eq(InteractionQuestion::getHidden, false) // 没有被隐藏的问题
                .page(questionPageQuery.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = page.getRecords();

        if (CollUtils.isEmpty(records)){
            return PageDTO.empty(page);
        }

        // 根据id查询最近依次回答和提问者的信息
        Set<Long> userIds = new HashSet<>();
        Set<Long> answerIds = new HashSet<>();

        // 查问题信息
        for (InteractionQuestion record : records) {
            // 只查询非匿名的问题
            if (!record.getAnonymity()) {
                userIds.add(record.getUserId());
            }
            answerIds.add(record.getLatestAnswerId());
        }
        
        // 查询回答信息
        Map<Long, InteractionReply> replyMap = new HashMap<>(answerIds.size());
        if (CollUtils.isNotEmpty(answerIds)){
            List<InteractionReply> replies = replyMapper.selectBatchIds(answerIds);
            for (InteractionReply reply : replies) {
                replyMap.put(reply.getId(),reply);
                if (!reply.getAnonymity()){ // 匿名用户不做查询
                    userIds.add(reply.getUserId());
                }
            }
        }

        // 根据id查询用户信息（提问者）
        Map<Long, UserDTO> userMap = new HashMap<>(userIds.size());
        if (CollUtils.isNotEmpty(userIds)){
            List<UserDTO> users = userClient.queryUserByIds(userIds);
            userMap = users.stream().collect(Collectors.toMap(UserDTO::getId,u->u));
        }

        // 封装vo
        List<QuestionVO> voList = new ArrayList<>(records.size());
        for (InteractionQuestion r : records) {
            QuestionVO questionVO = BeanUtils.copyBean(r, QuestionVO.class);
            // 分装提问者信息
            if (!r.getAnonymity()){
                UserDTO userDTO = userMap.get(r.getUserId());
                if (userDTO != null){
                    questionVO.setUserId(userDTO.getId());
                    questionVO.setUserName(userDTO.getName());
                    questionVO.setUserIcon(userDTO.getIcon());
                }
            }
            // 封装最后一次回答信息
            InteractionReply reply = replyMap.get(r.getLatestAnswerId());
            if (reply != null){
                questionVO.setLatestReplyContent(reply.getContent());
                if(!reply.getAnonymity()) {// 匿名用户直接忽略
                    UserDTO user = userMap.get(reply.getUserId());
                    log.info("回答问题用户信息:{}",user);
                    questionVO.setLatestReplyUser(user.getName());
                }
            }

            voList.add(questionVO);
        }
        return PageDTO.of(page,voList);
    }

    @Override
    public QuestionVO getByQuestion(Long id) {
        InteractionQuestion question = getById(id);
        // 判断问题是否存在或被隐藏
        if (question == null || question.getHidden()){
            return null;
        }
        QuestionVO questionVO = BeanUtils.copyBean(question, QuestionVO.class);
        // 查询提问者信息
        UserDTO user = null;
        if (!question.getHidden()) {
            // 只查询非匿名提问的用户信息
           user = userClient.queryUserById(question.getUserId());
        }
        if (user != null){
            questionVO.setUserIcon(user.getName());
            questionVO.setUserIcon(user.getIcon());
        }
        return questionVO;
    }

    @Override
    public PageDTO<QuestionAdminVO> pageAdminQuestions(QuestionAdminPageQuery questionPageQuery) {
        // 1.处理课程名称获取课程id
        List<Long> courseIds = null;
        if (StringUtils.isNotBlank(questionPageQuery.getCourseName())){
           courseIds = searchClient.queryCoursesIdByName(questionPageQuery.getCourseName());
        }
        if (CollUtils.isEmpty(courseIds)){
            return PageDTO.empty(0L,0L);
        }

        // 2.分页查询
        Integer status = questionPageQuery.getStatus();
        LocalDateTime begin = questionPageQuery.getBeginTime();
        LocalDateTime end = questionPageQuery.getEndTime();
        Page<InteractionQuestion> page = lambdaQuery().eq(status != null, InteractionQuestion::getStatus, status)
                .in(InteractionQuestion::getCourseId, courseIds)
                .gt(begin != null, InteractionQuestion::getCreateTime, begin)
                .lt(end != null, InteractionQuestion::getCreateTime, end)
                .page(questionPageQuery.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = page.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }

        // 获取用户id
        Set<Long> userIds = new HashSet<>();
        // 获取课程数据
        Set<Long> cIds = new HashSet<>();
        // 获取章节数据
        Set<Long> cataIds = new HashSet<>();

        // 获取各种数据的id集合
        for (InteractionQuestion record : records) {
            userIds.add(record.getUserId());
            cIds.add(record.getCourseId());
            cataIds.add(record.getChapterId());
            cataIds.add(record.getSectionId());
        }

        // 根据id查询用户
        Map<Long, UserDTO> userMap = new HashMap<>(userIds.size());
        List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
        if (CollUtils.isNotEmpty(userDTOS)){
             userMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        }

        // 根据id查询课程
        List<CourseSimpleInfoDTO> courseSimpleInfoDTOS = courseClient.getSimpleInfoList(cIds);
        Map<Long, CourseSimpleInfoDTO> courseMap = new HashMap<>(courseSimpleInfoDTOS.size());
        if (CollUtils.isNotEmpty(courseSimpleInfoDTOS)){
            courseMap = courseSimpleInfoDTOS.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));
        }

        // 根据id查询章和小结
        List<CataSimpleInfoDTO> cataSimpleInfoDTOS = catalogueClient.batchQueryCatalogue(cataIds);
        Map<Long, String> cataMap = new HashMap<>(cataSimpleInfoDTOS.size());
        if (CollUtils.isNotEmpty(cataSimpleInfoDTOS)){
            cataMap = cataSimpleInfoDTOS.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }

        // 封装vo数据
        List<QuestionAdminVO> questionAdminVOList = new ArrayList<>();
        for (InteractionQuestion record : records) {
            QuestionAdminVO questionAdminVO = BeanUtils.copyBean(record, QuestionAdminVO.class);
            UserDTO user = userMap.get(record.getUserId());
            if (user != null) {
                questionAdminVO.setUserName(user.getName());
            }
            CourseSimpleInfoDTO courseSimpleInfoDTO = courseMap.get(record.getCourseId());
            if (cataSimpleInfoDTOS != null){
                questionAdminVO.setCourseName(courseSimpleInfoDTO.getName());
                questionAdminVO.setCategoryName(categoryCache.getCategoryNames(courseSimpleInfoDTO.getCategoryIds()));
            }
            // 4.4.章节信息
            questionAdminVO.setChapterName(cataMap.getOrDefault(record.getChapterId(), ""));
            questionAdminVO.setSectionName(cataMap.getOrDefault(record.getSectionId(), ""));
            questionAdminVOList.add(questionAdminVO);
        }
        return PageDTO.of(page,questionAdminVOList);
    }

    @Override
    @Transactional
    public void removeQuestion(Long id) {
        // 查询要删除的问题是否存在
        InteractionQuestion question = getById(id);
        if (question == null){
            throw new BadRequestException("您要删除的问题不存在");
        }
        // 查询是否是当前登录用户的问题
        Long userId = UserContext.getUser();
        if (!question.getUserId().equals(userId)) {
            throw new BadRequestException("您要删除的问题不是您的问题");
        }
        // 删除question表中的信息
        boolean removeSuccess = removeById(id);
        if (!removeSuccess){
            throw new BadRequestException("删除问题信息失败");
        }
        replyMapper.delete(new LambdaQueryWrapper<InteractionReply>().eq(InteractionReply::getQuestionId,id));
    }

    @Override
    public void updateQuestion(Long id, QuestionFormDTO questionDTO) {
        // 标题和描述不能为空
        if (StringUtils.isBlank(questionDTO.getTitle()) || StringUtils.isBlank(questionDTO.getDescription())){
            throw new BadRequestException("标题和描述不能为空");
        }
        // 查询要修改的问题是否存在
        InteractionQuestion question = getById(id);
        if (question == null) {
            throw new BadRequestException("您要修改的问题不存在");
        }
        // 判断要修改的问题是否是当前登录用户的问题
        Long userId = UserContext.getUser();
        if (!question.getUserId().equals(userId)) {
            throw new BadRequestException("您要修改的问题不是您的问题");
        }
        question.setTitle(questionDTO.getTitle());
        question.setDescription(questionDTO.getDescription());
        question.setTitle(questionDTO.getTitle());
        updateById(question);
    }

    @Override
    public void updateHiddenStatus(Long id, Boolean hidden) {
        // 判断问题是否存在
        InteractionQuestion question = getById(id);
        if (question == null){
            throw new BadRequestException("您要修改的问题不存在");
        }
        question.setHidden(hidden);
        updateById(question);
    }

    @Override
    public QuestionAdminVO AdminGetByQuestion(Long id) {
        // 查询问题是否存在
        InteractionQuestion question = getById(id);
        if (question == null){
            throw new BadRequestException("该问题已经被删除");
        }

        QuestionAdminVO questionAdminVO = BeanUtils.copyBean(question, QuestionAdminVO.class);

        // 将章节和小结id加入到集合中,查询对应的name
        Set<Long> cataIs = new HashSet<>();
        cataIs.add(question.getSectionId());
        cataIs.add(question.getChapterId());
        List<CataSimpleInfoDTO> cataSimpleInfoDTOS = catalogueClient.batchQueryCatalogue(cataIs);
        if (CollUtils.isNotEmpty(cataSimpleInfoDTOS)){
            Map<Long, CataSimpleInfoDTO> cataSimpleInfoDTOMap = cataSimpleInfoDTOS.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, c -> c));
            questionAdminVO.setSectionName(cataSimpleInfoDTOMap.get(question.getSectionId()).getName());
            questionAdminVO.setChapterName(cataSimpleInfoDTOMap.get(question.getChapterId()).getName());
        }

        // 获取提问者信息
        Long userId = question.getUserId();
        UserDTO user = userClient.queryUserById(userId);

        // 获取课程信息
        CourseSearchDTO courseSearchDTO = courseClient.getSearchInfo(question.getCourseId());


        // 封装数据
        if (courseSearchDTO != null){
            // 获取老师信息
            UserDTO teacher = userClient.queryUserById(courseSearchDTO.getTeacher());
            questionAdminVO.setCourseName(courseSearchDTO.getName());
            questionAdminVO.setTeacherName(teacher.getName());
            questionAdminVO.setCategoryName(categoryCache.getCategoryNames(new CourseSimpleInfoDTO(courseSearchDTO.getCategoryIdLv1(),courseSearchDTO.getCategoryIdLv2(),courseSearchDTO.getCategoryIdLv3()).getCategoryIds()));
        }

        if (user != null){
            questionAdminVO.setUserName(user.getName()); // 提问者姓名
            questionAdminVO.setUserIcon(user.getIcon());
        }
        // 判断这个问题是否已经查看过
        if (question.getStatus() == QuestionStatus.UN_CHECK){
            question.setStatus(QuestionStatus.CHECKED);
            updateById(question);
        }
        return questionAdminVO;

    }
}
